﻿using log4net;
using MSDAL;
using MSWeb.Implementation;
using MSWeb.Models;
using PagedList;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web.Mvc;

namespace MSWEB.Implementation
{
    public class DataRepository
    {
        readonly ILog _loger = LogManager.GetLogger(typeof(DataRepository));
        private const int PageSize = 10;
        private readonly MSEntities _db;

        public DaneFirmy GetDaneFirmy()
        {
            if (!_db.DaneFirmy.Any())
            {
                return new DaneFirmy
                {
                    NazwaFirmy = "",
                    AdresFirmy = "",
                    IDFirmy = 0
                };
            }
            return
                _db
                    .DaneFirmy
                    .First();
        }

        public void SaveOrUpdateCompanyData(DaneFirmyModel companyModel)
        {
            var company = new DaneFirmy
            {
                AdresFirmy = companyModel.AdresFirmy,
                NazwaFirmy = companyModel.NazwaFirmy,
                IDFirmy = companyModel.IDFirmy
            };
            if (_db.DaneFirmy.Any(i => i.IDFirmy == company.IDFirmy))
            {
                _db.Entry(company).State = EntityState.Modified;
                _db.SaveChanges();
            }
            else
            {
                _db
                    .DaneFirmy
                    .Add(company);
                _db.SaveChanges();
            }
        }

        public IEnumerable<Uczniowie> GetStudentsBasedOnId(int studentId)
        {
            return _db.Uczniowie
                .Where(i => i.IDUcznia == studentId);
        }

        public IEnumerable<Nauczyciele> GetNauczycieleBasedOnId(int nauczycielId)
        {
            return _db.Nauczyciele
                .Where(i => i.IDNauczyciela == nauczycielId);
        }

        public DataRepository()
        {
            _db = new MSEntities();
        }

        public PaymentModel GetPaymentModelByWplataId(int id)
        {
            try
            {

                var payment = _db.Wplaty.First(i => i.WplataId == id);
                var result = new PaymentModel
                {
                    Lekcje = payment.Lekcje,
                    Data = payment.Data.Value,
                    Kwota = payment.Kwota.Value,
                    TypWplaty = payment.TypWplaty,
                    WplataId = payment.WplataId
                };
                return result;
            }
            catch (Exception ex)
            {
                _loger.Error("Error ", ex);
                return null;
            }
        }

        public string GetColorPlNameById(int id)
        {
            try
            {
                return _db.Colors
                    .FirstOrDefault(i => i.IdKoloru == id)
                    .NazwaAngielska;
            }
            catch (Exception ex)
            {
                _loger.Error("Error ", ex);
                return string.Empty;
            }
        }

        public IEnumerable<SelectListItem> GetLessonBasedOnStudentId(int studentId)
        {
            try
            {
                var aktualnaData = DateTime.Now;
                var data = _db.Lekcje
                    .Where(i => i.IDUcznia == studentId
                        && i.Data.Value.Month <= aktualnaData.Month
                        && i.Data.Value.Year <= aktualnaData.Year
                                && i.WplataId == null && i.CzyUsunieta != true).ToList();
                IList<SelectListItem> items = data.Select(item => new SelectListItem
                {
                    Value = item.IDLekcji.ToString(),
                    Text = "Data: " + item.Data.ToString()
                           + " Sala: " + item.Sale.NazwaSali
                           + " Nauczyciel: " + item.Nauczyciele.Imie + " " + item.Nauczyciele.Nazwisko
                           + " Cena: " + item.KosztLekcji
                }).ToList();
                return items;
            }
            catch (Exception ex)
            {
                _loger.Error("Error ", ex);
                return null;
            }
        }

        public IEnumerable<SelectListItem> GetLessonBasedOnTeacherId(int nauczycielId)
        {
            try
            {
                var data = _db.Lekcje
                    .Where(i => i.IDNauczyciela == nauczycielId && i.CzyZatwierdzona.Value
                                && i.WyplataId == null).ToList();
                IList<SelectListItem> items = data.Select(item => new SelectListItem
                {
                    Value = item.IDLekcji.ToString(),
                    Text = "Data: " + item.Data.ToString()
                           + " Sala: " + item.Sale.NazwaSali
                           + " Uczeń: " + item.Uczniowie.Imie + " " + item.Uczniowie.Nazwisko
                           + " Wynagrodzenie: " + item.Nauczyciele.WynagrodzenieZaLekcje
                }).ToList();
                return items;
            }
            catch (Exception ex)
            {
                _loger.Error("Error ", ex);
                return null;
            }
        }

        public Lekcje GetLessonById(int id)
        {
            try
            {
                return _db.Lekcje
                    .FirstOrDefault(i => i.IDLekcji == id);
            }
            catch (Exception ex)
            {
                _loger.Error("Error ", ex);
                return null;
            }
        }

        public string GetNameAndSurnameForStudent(int id)
        {
            try
            {
                var result = string.Empty;
                if (!_db.Uczniowie.Any(i => i.IDUcznia == id)) return result;
                var student = _db.Uczniowie.FirstOrDefault(i => i.IDUcznia == id);
                if (student != null) result = student.Imie + " " + student.Nazwisko;
                return result;
            }
            catch (Exception ex)
            {
                _loger.Error("Error ", ex);
                return null;
            }
        }

        public string GetNameAndSurnameForTeacher(int id)
        {
            try
            {
                var result = string.Empty;
                if (!_db.Nauczyciele.Any(i => i.IDNauczyciela == id)) return result;
                var teacher = _db.Nauczyciele.FirstOrDefault(i => i.IDNauczyciela == id);
                if (teacher != null) result = teacher.Imie + " " + teacher.Nazwisko;
                return result;
            }
            catch (Exception ex)
            {
                _loger.Error("Error ", ex);
                return null;
            }
        }

        public Uczniowie GetStudentById(int id)
        {
            return _db.Uczniowie
                .FirstOrDefault(i => i.IDUcznia == id);
        }

        public Nauczyciele GetNauczycielById(int id)
        {
            return _db.Nauczyciele
                .FirstOrDefault(i => i.IDNauczyciela == id);
        }

        //naleznosci dla nauczycieli
        public IEnumerable<ListaDluznikowViewModel> ReturnListOfReceivables(int? page)
        {
            var pageNumber = (page ?? 1);
            var result = new List<ListaDluznikowViewModel>();
            try
            {
                _db.Nauczyciele.ToList().ForEach(item =>
                {
                    result.Add(new ListaDluznikowViewModel
                    {
                        PersonId = item.IDNauczyciela,
                        ImieNazwisko = item.Imie + " " + item.Nazwisko,
                        Debet = 0d,
                    });
                });
                result.ForEach(item =>
                {
                    if (_db.Lekcje.Any(i => i.IDNauczyciela == item.PersonId))
                    {
                        var sum = _db.Lekcje.Where(i => i.IDNauczyciela == item.PersonId && i.CzyZatwierdzona.Value
                            && i.CzyUsunieta != true && i.WyplataId == null && i.WynagrodzenieNauczyciela != null)
                            .Sum(i => i.WynagrodzenieNauczyciela);
                        item.Debet = sum;
                        item.MaxData = _db.Lekcje.Where(i => i.IDNauczyciela == item.PersonId
                            && i.CzyUsunieta != true && i.WyplataId == null && i.Data != null && i.WynagrodzenieNauczyciela != null)
                            .Min(i => i.Data);
                    }                 
                });
                var aktualnaData = DateTime.Now;
                result.ForEach(item =>
                {
                    item.OstatniaDataIni = Math.Abs(DaysBetween(aktualnaData, item.MaxData.Value)) + " dni temu.";
                });
                result = result.Where(i => i.Debet != 0).ToList();
            }
            catch (Exception ex)
            {
                _loger.Error("Error ", ex);
            }
            return result
                   .OrderBy(i => i.PersonId)
                   .ToPagedList(pageNumber, PageSize);
        }

        int DaysBetween(DateTime d1, DateTime d2)
        {
            TimeSpan span = d2.Subtract(d1);
            return (int)span.TotalDays;
        }

        //lista dluznikow
        public IEnumerable<ListaDluznikowViewModel> ReturnListOfDeptorNewVersion(int? page)
        {
            var pageNumber = (page ?? 1);
            var result = new List<ListaDluznikowViewModel>();
            try
            {
                _db.Uczniowie.ToList().ForEach(item =>
                {
                    result.Add(new ListaDluznikowViewModel
                    {
                        PersonId = item.IDUcznia,
                        ImieNazwisko = item.Imie + " " + item.Nazwisko,
                        Debet = 0d
                    });
                });
                result.ForEach(item =>
                {
                    if (_db.Lekcje.Any(i => i.IDUcznia == item.PersonId))
                    {
                        var sum = _db.Lekcje.Where(i => i.IDUcznia == item.PersonId
                            && i.CzyUsunieta != true && i.WplataId == null && i.KosztLekcji != null)
                            .Sum(i => i.KosztLekcji);
                        item.Debet = sum;
                        item.MaxData = _db.Lekcje.Where(i => i.IDUcznia == item.PersonId
                            && i.CzyUsunieta != true && i.WplataId == null && i.Data != null && i.KosztLekcji != null)
                            .Min(i => i.Data);
                    }
                });                
                var aktualnaData = DateTime.Now;
                result.ForEach(item =>
                {
                    item.OstatniaDataIni = Math.Abs(DaysBetween(aktualnaData, item.MaxData.Value)) + " dni temu.";
                });
                result = result.Where(i => i.Debet != 0).ToList();
            }
            catch (Exception ex)
            {
                _loger.Error("Error ", ex);
            }
            return result
               .OrderBy(i => i.PersonId)
               .ToPagedList(pageNumber, PageSize);
        }

        public bool SavePaymentForTeacher(WyplataZaLekcjeDodaj paymentForTeacherViewModel)
        {
            using (var dbContextTransaction = _db.Database
                .BeginTransaction(IsolationLevel.ReadUncommitted))
            {
                try
                {
                    var payment = new Wyplaty
                    {
                        CzyUsunieta = false,
                        Data = DateTime.Now,
                        Komentarz = paymentForTeacherViewModel.Komentarz,
                        Kwota = Math.Round(paymentForTeacherViewModel.Kwota, 2),
                        TypWplaty = paymentForTeacherViewModel.TypWyplatyZaLekcje.ToString()
                    };
                    _db.Wyplaty.Add(payment);
                    _db.SaveChanges();
                    foreach (var item in paymentForTeacherViewModel.SelectedLekcje)
                    {
                        var lessonId = int.Parse(item);
                        var lessonForPayment = _db.Lekcje
                            .FirstOrDefault(j => j.IDLekcji == lessonId);
                        if (lessonForPayment != null)
                        {
                            lessonForPayment.WyplataId = payment.WyplataId;
                            _db.Entry(lessonForPayment).State = EntityState.Modified;
                        }
                        _db.SaveChanges();
                    }
                    dbContextTransaction.Commit();
                }
                catch (Exception ex)
                {
                    _loger.Error("Error ", ex);
                    dbContextTransaction.Rollback();
                    return false;
                }
            }
            return true;
        }

        public bool SavePayment(WplataZaLekcjeDodaj paymentForLessonViewModel)
        {
            using (var dbContextTransaction = _db.Database
                .BeginTransaction(IsolationLevel.ReadUncommitted))
            {
                try
                {
                    var payment = new Wplaty
                    {
                        CzyUsunieta = false,
                        Data = DateTime.Now,
                        Komentarz = paymentForLessonViewModel.Komentarz,
                        Kwota = Math.Round(paymentForLessonViewModel.Kwota, 2),
                        TypWplaty = paymentForLessonViewModel.typWplatyZaLekcje.ToString()
                    };
                    _db.SaveChanges();
                    _db.Wplaty.Add(payment);
                    foreach (var item in paymentForLessonViewModel.SelectedLekcje)
                    {
                        var lekcjeId = int.Parse(item);
                        var lessonForPayment = _db.Lekcje
                            .FirstOrDefault(j => j.IDLekcji == lekcjeId);
                        if (lessonForPayment != null)
                        {
                            lessonForPayment.WplataId = payment.WplataId;
                            _db.Entry(lessonForPayment).State = EntityState.Modified;
                        }
                        _db.SaveChanges();
                    }
                    dbContextTransaction.Commit();
                }
                catch (Exception ex)
                {
                    _loger.Error("Error ", ex);
                    dbContextTransaction.Rollback();
                    return false;
                }
            }
            return true;
        }

        public List<Events> GetEvents(DateTime from, DateTime to)
        {
            var lekcje = new List<Lekcje>();
            try
            {
                var res = _db.Lekcje
                        .Include(l => l.Nauczyciele)
                        .Include(l => l.Sale)
                        .Include(l => l.Uczniowie)
                        .Where(i => i.Data.Value.Year == from.Date.Year
                        && i.Data.Value.Month == from.Date.Month
                        && i.Data.Value.Day == from.Date.Day)
                        .ToList();
                var eventList = new List<Events>();
                res.ForEach(lekcja =>
                {
                    var dataPlus = lekcja.Data.Value.AddHours(1);
                    eventList.Add(new Events
                    {
                        id = lekcja.IDLekcji.ToString(),
                        start = lekcja.Data.Value.ToString("s"),
                        end = dataPlus.ToString("s"),
                        allDay = false,
                        title = lekcja.Nauczyciele.Instrument + " " +
                            lekcja.Uczniowie.Imie + " " + lekcja.Uczniowie.Nazwisko
                    });
                });
                return eventList;
            }
            catch (Exception ex)
            {
                _loger.Error("Error ", ex);
                return new List<Events>();
            }
        }

        public IEnumerable<SelectListItem> GetNauczyciele()
        {
            IList<SelectListItem> items = new List<SelectListItem>();
            _db.Nauczyciele.OrderBy(i => i.Imie)
                .ToList().ForEach(item =>
            {
                items.Add(new SelectListItem
                {
                    Value = item.IDNauczyciela.ToString(),
                    Text = item.Imie + " " + item.Nazwisko
                });
            });
            return items;
        }

        public List<Uczniowie> GetActiveStudents()
        {
            var result = _db.Uczniowie
                .Where(i => i.CzyUsunieta == false)
                .ToList();
            return result;
        }

        public IEnumerable<SelectListItem> GetUczniowie()
        {
            IList<SelectListItem> items = new List<SelectListItem>();
            _db.Uczniowie
                .ToList().ForEach(item =>
            {
                items.Add(new SelectListItem
                {
                    Value = item.IDUcznia.ToString(),
                    Text = item.Imie + " " + item.Nazwisko
                });
            });
            return items;
        }
    }
}
